package ro.gateway.aida.admin;


import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;

import ro.gateway.aida.db.PersistenceToken;
import ro.gateway.aida.obj.db.SystemPropertyDB;


/**
 * <p>Title: Romanian AIDA</p>
 * <p>Description: :D application</p>
 * <p>Copyright: Copyright (comparator) 2003</p>
 * <p>Company: Romania Development Gateway </p>
 * <p/>
 * Singleton.
 * Kepps the activity objects options.
 *
 * @author Mihai Popoaei, mihai_popoaei@yahoo.com, smike@intellisource.ro
 * @version 1.0-* @version $Id: ActivityObjectsOptions.java,v 1.1 2004/10/24 23:37:18 mihaipostelnicu Exp $
 */
public class ActivityObjectsOptions {

      // key = object name (for example approval_date)
      // value = ObjectOption, masks (@the end): MANDATORY_MASK, ENABLED_MASK
      Hashtable object_properties = new Hashtable();
      // ranking fields
      ArrayList ordered_ooptions = new ArrayList();

      private ActivityObjectsOptions () {
      }

      private static ActivityObjectsOptions the_instance = null;

      public static ActivityObjectsOptions getInstance () {
            if ( the_instance == null ) the_instance = new ActivityObjectsOptions();

            return the_instance;
      }

      /**
       * default: not mandatory, disabled
       *
       * @param name
       */
      public void register ( String name ) {
            if ( name == null ) {
                  throw new RuntimeException( "Invalid object name" );
            }

            if ( object_properties.get( name ) == null ) {
                  object_properties.put( name, new ObjectOption( name, 0 ) );
                  _make_ordered_list();
            }
      }

      public String[] getRegisteredObjects () {
            if ( ordered_ooptions.size() == 0 ) return null;

            String[] result = new String[ ordered_ooptions.size() ];
            for ( int i = 0; i < result.length; i++ ) {
                  result[ i ] = ( ( ObjectOption ) ordered_ooptions.get( i ) ).name;
            }

            return result;
      }

      public void setOptions ( String name, int options ) {
            if ( name == null ) return;
            register( name );

            Object obj = object_properties.get( name );
            if ( obj == null ) return;

            ( ( ObjectOption ) obj ).options = options;
      }

      public void setEnabled ( String name, boolean enabled ) {
            if ( name == null ) return;
            register( name );

            Object obj = object_properties.get( name );
            if ( obj == null ) return;

            int options = ( ( ObjectOption ) obj ).options;
            options = enabled ? ( options | ObjectOption.ENABLED_MASK ) : ( options & ( ~ObjectOption.ENABLED_MASK ) );
            ( ( ObjectOption ) obj ).options = options;
      }

      public boolean isEnabled ( String name ) {
            if ( name == null ) return false;
            Object obj = object_properties.get( name );
            if ( obj == null ) return false;

            int options = ( ( ObjectOption ) obj ).options;
            return ( options & ObjectOption.ENABLED_MASK ) != 0;
      }

      public boolean areEnabled ( String[] names ) {
            if ( names == null ) return true;

            for ( int i = 0; i < names.length; i++ ) {
                  String name = names[ i ];
                  if ( !isEnabled( names[ i ] ) ) return false;
            }

            return true;
      }

      public boolean isOneEnabled ( String[] names ) {
            if ( names == null ) return false;

            for ( int i = 0; i < names.length; i++ ) {
                  String s = names[ i ];
                  if ( isEnabled( names[ i ] ) ) return true;
            }

            return false;
      }

      public void setMandatory ( String name, boolean enabled ) {
            if ( name == null ) return;
            register( name );

            Object obj = object_properties.get( name );
            if ( obj == null ) return;

            int options = ( ( ObjectOption ) obj ).options;
            options = enabled ? ( options | ObjectOption.MANDATORY_MASK ) : ( options & ( ~ObjectOption.MANDATORY_MASK ) );
            ( ( ObjectOption ) obj ).options = options;
      }

      public int getIntOptions ( String name ) {
            if ( name == null ) return -1;
            Object obj = object_properties.get( name );
            if ( obj == null ) return -1;

            int options = ( ( ObjectOption ) obj ).options;
            return options;
      }

      public void loadFromString ( String s_props ) {
            if ( s_props == null ) return;
            Properties props = new Properties();
            try {
                  BufferedReader reader = new BufferedReader( new StringReader( s_props ) );
                  String line = null;
                  while ( ( line = reader.readLine() ) != null ) {
                        if ( line.startsWith( "#" ) )
                              continue;
                        int idx1 = line.indexOf( "=" );
                        int idx2 = line.indexOf( ":" );
                        if ( idx1 == -1 || idx2 == -1 ) continue;
                        String key = line.substring( 0, idx1 );
                        try {
                              int rank = new Integer( line.substring( idx1 + 1, idx2 ) ).intValue();
                              int value = new Integer( line.substring( idx2 + 1 ) ).intValue();
                              ObjectOption opt = new ObjectOption( key, value );
                              opt.rank = rank;
                              object_properties.put( key, opt );
                        } catch ( Exception ex ) {

                        }
                  }
                  reader.close();
            } catch ( Throwable thr ) {
                  thr.printStackTrace();
            }
            _make_ordered_list();
      }

      public void loadFromProperties ( InputStream is )
            throws IOException {
            Properties props = new Properties();

            Vector v = new Vector();
            props.load( is );

            Enumeration en = props.keys();
            while ( en.hasMoreElements() ) {
                  String key = ( String ) en.nextElement();
                  int value = 0;
                  int rank = 0;
                  try {
                        String s_value = props.getProperty( key );
                        int marker_index = s_value.indexOf( ':' );
                        if ( marker_index > 0 ) {
                              try {
                                    rank = new Integer( s_value.substring( 0, marker_index ) ).
                                          intValue();
                                    value = new Integer( s_value.substring( marker_index + 1 ) ).
                                          intValue();
                              } catch ( Exception ex ) {
                              }
                        } else {
                              value = new Integer( s_value ).intValue();
                        }
                  } catch ( NumberFormatException nfEx ) {
                        nfEx.printStackTrace();
                  }
                  ObjectOption opts_i = new ObjectOption( key, value );
                  opts_i.rank = rank;
                  object_properties.put( key, opts_i );
//                  System.out.println( "from properties:" + key + "=" + value );
            }

            _make_ordered_list();
      }

      private void _make_ordered_list () {
            if ( object_properties.size() < 1 ) return;

            Collection values = object_properties.values();
            ObjectOption options_arr[] = new ObjectOption[ values.size() ];
            values.toArray( options_arr );


            Arrays.sort( options_arr, new Comparator() {
                  public int compare ( Object o1, Object o2 ) {
                        ObjectOption oo1 = ( ObjectOption ) o1;
                        ObjectOption oo2 = ( ObjectOption ) o2;
                        return oo1.rank < oo2.rank ? -1 :
                              ( oo1.rank > oo2.rank ? 1 : 0 );
                  }
            } );

            ordered_ooptions.clear();
            for ( int i = 0; i < options_arr.length; i++ ) {
                  ordered_ooptions.add( options_arr[ i ] );
            }

//            for ( int i = 0; i < ordered_ooptions.size(); i++ )
//            {
//                  ObjectOption objectOption = ( ObjectOption ) ordered_ooptions.get( i );
//                  System.out.println( objectOption.name + "=" + objectOption.rank + "," + objectOption.options );
//            }
      }

      public void saveToFile ( String file_name )
            throws IOException {
            Properties props = new Properties();

            for ( int i = 0; i < ordered_ooptions.size(); i++ ) {
                  ObjectOption objectOption = ( ObjectOption ) ordered_ooptions.get( i );
                  props.setProperty( objectOption.name,
                        String.valueOf( objectOption.rank ) + ":" +
                        String.valueOf( objectOption.options ) );
            }

            FileOutputStream os = new FileOutputStream( file_name );
            props.store( os, "Activities objects defs" );
            os.close();
      }

      public void saveToDB ( PersistenceToken token ) {

            StringBuffer sb = new StringBuffer();
            for ( int i = 0; i < ordered_ooptions.size(); i++ ) {
                  ObjectOption objectOption = ( ObjectOption ) ordered_ooptions.get( i );
                  sb.append( objectOption.name ).append( "=" )
                        .append( objectOption.rank ).append( ":" )
                        .append( objectOption.options ).append( "\n" );
            }

            try {
                  SystemPropertyDB.getManager( token )
                        .setProperty( "actoobjoptions", sb.toString() );
            } catch ( SQLException sqlex ) {
                  sqlex.printStackTrace();
            }
      }

      public boolean isMandatory ( String name ) {
            if ( name == null ) return false;
            Object obj = object_properties.get( name );
            if ( obj == null ) return false;

            int options = ( ( ObjectOption ) obj ).options;
            return ( options & ObjectOption.MANDATORY_MASK ) != 0;
      }

      public static void main ( String args[] ) {
            try {
                  Class clasa = Class.forName( "ro.gateway.aida.admin.ActObjsOptsConst" );
                  Field[] fields = clasa.getDeclaredFields();
                  for ( int i = 0; i < fields.length; i++ ) {
                        Field field = fields[ i ];
//                        System.out.println( field.getName() + "=" + field.get( null ) );
                  }

            } catch ( Exception ex ) {
                  ex.printStackTrace();
            }
            new ActivityObjectsOptions();

            if ( 1 == 1 ) return;

            ActivityObjectsOptions x = new ActivityObjectsOptions();

//            System.out.println( x.isEnabled( "xxx" ) );
            x.setEnabled( "xxx", true );
//            System.out.println( x.isEnabled( "xxx" ) );
            x.setEnabled( "xxx", false );
//            System.out.println( x.isEnabled( "xxx" ) );
            x.setEnabled( "xxx", true );
//            System.out.println( x.isEnabled( "xxx" ) );
            x.setMandatory( "yy", true );

            String[] objs = x.getRegisteredObjects();
            if ( objs != null )
                  for ( int i = 0; i < objs.length; i++ ) {
                        String obj = objs[ i ];
//                        System.out.println( obj + " " );
                  }
      }

}
